這個章節主要是介紹物件的結構,和他本身所擁有的各種預設的方法。
有兩種形式
var declarativeObj = {
key: value
}
var constructedObj = new Object();
constructedObj.key = value;
差異
複習。
六大主要型別 ( symbol 不算在內 )。
「 JavaScript 的一切都是物件 」,這顯然不是真確的。
其中 null 是 primitive type,別被 typeof null 混淆了。
複習 Native。
可以當作建構器使用。
簡單分類
var strPrimitive = "I am a string";
typeof strPrimitive; // "string"
strPrimitive instanceof String; // false ??!!?!?
var strObject = new String( "I am a string" );
typeof strObject; // "Object"
strObject instanceof String; // true ??!!?!?!!?
之後會講解 Object.prototype.toString...的部分運作的細節。
為什麼純值會有方法可以用?
var strPrimitive = "I am a string";
console.log( strPrimitive.length ); // 13
console.log( strPrimitive.charAt( 3 )); // "m"
在純值上呼叫屬性和方法,JS會強制轉型為 string 物件。
其他是否能呼叫建構式,書上又再複習了一下。
PS. 書上慣用特性來稱呼 property,但 Tony 習慣用屬性。
物件的內容 ( contents ) 由值 ( value ) 構成。
儲存在命名過的位置 ( locations ),叫做屬性 ( properties )。
但真正儲存在容器中的,是屬性名稱,是參考 ( referances )。
有兩種用屬性取得值的方式
var myObj = {
a: 2
};
myObj.a; // 2 property access ( 後續以這個為主 )
myObj["a"]; // 2 key access
[..] 的特性
-
, !
這對 Tony 來說是很神奇的方法,看看吧。
var prefix = "foo";
var myObject = {
[prefix + "bar"]: "hello",
[prefix + "baz"]: "world"
}
myObject[ "foobar" ]; // hello
myObject[ "foobaz" ]; // world
嚴格來說,函式永遠都不會屬於物件。
每次存取一個物件上的屬性,那就是一次屬性存取,不管是什麼值,他都不會變成方法。
function foo() {
console.log( "foo" );
}
var someFoo = foo;
var myObject = {
someFoo: foo
};
foo; // 直接呼叫
somefoo; // 藉由函式運算式呼叫
myObject; // 藉由物件屬性呼叫
以上都會出現 function foo(){..}
,都是指向 foo 的不同參考。
在 JavaScript 中,函式 ( function ) 與 方法 ( method ) 是可以互換的名詞。
就算值使用函式運算式也是多個參考之一。
var myObject = {
foo: function foo() {
console.log( "foo" );
}
}
var someFoo = myObject.foo;
someFoo; // function foo(){..}
myObject.foo; // function foo(){..}
為什麼在寫一次?
因為 foo: function foo(){..}
,在 ES6 有其他寫法。
陣列也是用鍵值存取 [..] 的形式。和物件的差別在使用數值索引。以非負整數來編號 0, 1, .., n
列出特性
"3"
當鍵值,會當成是 number 索引使用。如何複製一個物件?
這邊牽扯到 深拷貝 與 淺拷貝。
簡單的例子,說明淺拷貝。
var a = [1, [2, 3]];
var b = Array.from(a);
b[0] = 4;
a; // [1, [2, 3]]
b; // [4, [2, 3]] 第一層已經拷貝了
b[1][0] = 10;
a; // [1, [10, 3]]
b; // [1, [10, 3]] 內層依然指向相同的位置
淺拷貝,會把第一層的值,另外做一個複製品。其他層的會用相同的參考。
那深拷貝呢?
從 a 物件 拷貝一個 b 物件
當修改 b 物件的任何內容,不管多深,a 的內容都不會跟著變動。
var anObject = {
b: true
};
function aFunction() { /*..*/ }
var anArray = []; // 創建 Object, Function, Array
var obj = {
a: 2,
b: anObject,
c: aFunction,
d: anArray
};
anArray.push( anObject, obj );
會有個無限的循環參考
而上面的例子展現了循環參考( circular reference )。
這和深拷貝和淺拷貝有什麼關係?
( Tony 還沒意會過來,但覺得這樣能用循環參考很酷 )
那如何複製物件呢?
var newObj = JSON.parse( JSON.stringify( obj ) );
把物件轉成 JSON 字串,再重新剖析成物件,並存在新物件中。
assign( target, source );
可以將 source 的可列舉自有鍵值,複製到 target 上。
var newObj = Object.assign( {}, obj );
會講到屬性描述器,取值送值和迭代。
屬性描述器有打到 Tony 的腦洞啊!